import 'dart:convert';
import '../extension/ex_safe.dart';
import '../utils/storage.dart';
import 'package:intl/intl.dart';
import 'package:crypto/crypto.dart';
import 'package:convert/convert.dart';
import 'package:encrypt/encrypt.dart';
import '../values/constants.dart';


/// 数据缓存工具
class DataCacheUtil {

  // 默认缓存时长(默认8小时)
  static const double _cacheTime = 8.00;

  // 全局访问
  static DataCacheUtil share() {
    _instance ??= DataCacheUtil._internal();
    return _instance!;
  }

  // 保存实例
  static DataCacheUtil? _instance;

  DataCacheUtil._internal();

  /// 时间格式
  final String _format = 'yyyy-MM-dd HH:mm:ss';

  /// 数据缓存key
  String? _cacheKey;

  /// 缓存key
  String get cacheKey => _showCacheKey();

  /// 处理数据展示
  String _showCacheKey() {
    _cacheKey ??= DCEncrypt.encodeMd5('speed_data_cache_key');
    return _cacheKey ?? '';
  }

  /// 取值和存储key的生产规则
  /// [url] 缓存唯一key值
  /// [params] 唯一key后拼接可变参数
  String localKey(String url, Map<String, dynamic>? params) {
    /// 参数转换成JSON作为key的一部分
    String jsonString = json.encode(params);
    if (jsonString.exStr.isNotEmpty && jsonString != 'null') {
      return '$cacheKey@${DCEncrypt.encodeMd5(url)}@${DCEncrypt.encodeMd5(jsonString)}';
    }else {
      return '$cacheKey@${DCEncrypt.encodeMd5(url)}';
    }
  }

  /// 计算缓存时间是否过期（过期删除，暂时为缓存8小时）
  /// [dateString] 取得的缓存数据(包含存储时间字段)
  /// [time] 缓存过期时长判断(默认值，单位小时)
  /// [result] 是否过期
  bool _expired (String dateString,{double? time = _cacheTime}) {
    if (time == null || time <= 0) return false;
    if (dateString.length == _format.length) {
      // 字符串时间解析
      DateTime dateTime = DateFormat(_format).parse(dateString);
      // 获取当前时间
      DateTime now = DateTime.now();
      // 计算时间差
      Duration difference = now.difference(dateTime);
      if (difference.inSeconds <= time  * 3600) return false;
    }
    return true;
  }

  /// 根据url和参数获取本地
  /// [url] 缓存唯一key值
  /// [params] 唯一key后拼接可变参数
  /// [time] 缓存过期时长判断(默认值，单位小时)
  /// [result]返回结果
  dynamic getCacheData(String url,{Map<String, dynamic>? params,double? time = _cacheTime}) {
    /// 取值key
    String key = localKey(url, params);
    /// 获取缓存数据库数据
    var data = Storage().getString(key);
    if (data.isNotEmpty) {
      /// AES解密获取base64
      String base64 = DCEncrypt.aesDecrypt(data);
      /// 解析JSON数据
      dynamic cacheData = jsonDecode(base64);
      if (_expired(cacheData['time'], time: time) == false) {
        /// 返回缓存结果
        return cacheData['data'];
      }else {
        /// 删除过期数据
        Storage().remove(key);
      }
    }
    return null;
  }

  /// 持久化保存定位地址
  /// [url] 保存缓存唯一key值
  /// [params] 唯一key后拼接可变参数
  void saveCacheData(String url, dynamic data, {Map<String, dynamic>? params}) {
    if (data == null) return;
    /// 构建保存key
    String key = localKey(url, params);
    /// 缓存的map
    Map saveMap = {
      'time':DateFormat(_format).format(DateTime.now()),/// 当前时间
      'data':data,
    };
    /// 转JSON格式
    String jsonString = json.encode(saveMap);
    /// base64通过AES加密
    dynamic aes = DCEncrypt.aesEncrypt(jsonString);
    /// AES加密后存储本地
    Storage().setString(key,aes);
  }
  /// 移除缓存：参数[all]是否全部移除
  /// ***[all]为true时，如果url为空，删除所有以cacheKey开头的数据;
  /// ****** url不为空时，删除cacheKey与url的组合key
  /// ***[all]为false时，会删除cacheKey、url、params的组合key
  Future<bool> removeCache(String url,{Map<String, dynamic>? params,bool? all}) async {
    if (all == true) {
      /// 删除以url开头的数据
      String removeKey = cacheKey;
      if (url.isNotEmpty) {
        /// 构建保存key
        removeKey = localKey(url,null);
      }
      /// 所有开头
      return await Storage().removeStart(removeKey);
    }else {
      /// 构建保存key
      String key = localKey(url, params);
      return await Storage().remove(key);
    }
  }
}

/// 加密工具
class DCEncrypt {

  /// Base64编码
  static String encodeBase64(String data) {
    return base64Encode(utf8.encode(data));
  }

  /// Base64解码
  static String decodeBase64(String data) {
    return String.fromCharCodes(base64Decode(data));
  }

  /// md5 加密
  static String encodeMd5(String data) {
    var content = const Utf8Encoder().convert(data);
    var digest = md5.convert(content);
    return hex.encode(digest.bytes);
  }
  /// AES加密
  static aesEncrypt(plainText) {
    try {
      // 此处要与后端保持一致
      final key = Key.fromUtf8(Constants.aesKey);
      final iv = IV.fromUtf8(Constants.aesIV);
      final cipher = Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7'));
      final encrypted = cipher.encrypt(plainText, iv: iv);
      return encrypted.base64;
    } catch (err) {
      // print('AES encode error:$err');
      return plainText;
    }
  }

  /// AES解密
  static dynamic aesDecrypt(encrypted) {
    try {
      // 此处要与后端保持一致
      final key = Key.fromUtf8(Constants.aesKey);
      final iv = IV.fromUtf8(Constants.aesIV);

      final cipher = Encrypter(AES(key, mode: AESMode.cbc, padding: 'PKCS7'));
      final decrypted = cipher.decrypt64(encrypted, iv: iv);
      return decrypted;
    } catch (err) {
      // print('AES decode error:$err');
      return encrypted;
    }
  }
}